<?php
namespace app\admin\service;
use app\common\library\Service;

class Module extends Service
{
    /**
     * 引入后台控制器的traits
     */
    use \app\common\library\traits\Model;


	public function __construct() {
		$this->model = model('admin/module');
	}

    public function fetch($identifier = '', $merge = false) {
        $path = APP_PATH.$identifier.DS;
        if(!file_exists($path.$identifier.'.xml')) {
            $this->error = lang('模块配置文件（'.$identifier.'.xml）不存在');
            return false;
        }
        $conf_xml = file_get_contents($path.$identifier.'.xml');
        $data = xml2array($conf_xml);
        $data['status'] = -1;
        $info = $this->model->field('identifier,name,config,version,dependencies,sort,status')->find($identifier);
        if($info) {
            $info = $info->toArray($info);
            $data = array_merge($data, $info);
        }
        return $data;
    }

    public function fetch_all() {
        $path = APP_PATH;
        $ms = glob($path.'*/*.xml');
        foreach ($ms as $key => $m) {
            $dir = pathinfo($m);
            $identifier = $dir['filename'];
            $modules[] = $this->fetch($identifier);
        }
        return $modules;
    }

    public function execute($identifier = '', $action = 'install') {
        if(!in_array($action, ['install', 'upgrade', 'uninstall'])) {
            $this->error = '非法请求';
            return false;
        }
        $info = $this->fetch($identifier, true);
        if($info === false) {
            return false;
        }
        // 1、依赖检测
    	if($info['dependencies'] && !$this->_depend($info['dependencies'], $action)) {
    		return false;
    	}
    	// 2、执行操作
    	if(!$this->$action($info)) {
    		return false;
    	}



        // rule
        model('AuthRule')->where('module', $identifier)->delete();
        if($action != 'uninstall') {
        	$this->_rules($info['rules'], $identifier);
        }

        // tag 未更新缓存
        \think\Hook::listen('module_'.$action, $info);

        // clear
        \think\Cache::clear();

        // tag - 已更新缓存
        \think\Hook::listen('module_execute',$info);

        return $info;
    }


    public function config($identifier, array $param = []) {
        $info = $this->model->find($identifier);
        $config = [];
        foreach ($info['config'] as $key => $value) {
            $value['value'] = $param[$key];
            $config[$key] = $value;
        }
        $info->config = $config;
        $result = $info->save();
        if($result === false) {
            return false;
        }
        \think\Cache::clear();
        \think\Hook::listen('module_config',$info);
        return true;
    }


    /* 安装模块 */
    protected function install(array $xml = []) {
    	if($xml['status'] != -1) {
    		$this->error = lang('此模块尚已安装，无法重复安装操作');
    		return false;
    	}
    	$this->_execute($xml['identifier'], 'install');
    	// 写入模块
    	$result = $this->model->validate(true)->save($xml);
    	if($result === false) {
    		return false;
    	}
    	return $xml;
    }

    protected function upgrade(array $xml = []) {
    	if($xml['status'] != -1) {
    		$this->error = lang('此模块尚未安装，无法执行升级操作');
    		return false;
    	}
    	$this->_execute($xml['identifier'], 'upgrade');
    	// 写入模块
    	$result = $this->model->validate(true)->save($xml);
    	if($result === false) {
    		return false;
    	}
    	return $xml;
    }

    protected function uninstall(array $xml = []) {
    	if($xml['status'] == -1) {
    		$this->error = lang('此模块尚未安装，无法执行卸载操作');
    		return false;
    	}
    	$this->_execute($xml['identifier'], 'uninstall');
    	// 写入模块
    	$result = $this->model->where('identifier', $xml['identifier'])->delete();
    	if($result === false) {
    		return false;
    	}
    	return $xml;
    }


    protected function _execute($identifier, $action = 'install') {
    	$command = APP_PATH.$identifier.DS. 'command'. DS;
        $querys = $incfiles = [];
        if(file_exists($command.$action.'.sql')) {
            $querys[] = $command.$action.'.sql';
        }
        if(file_exists($command.$action.'.php')) {
            $incfiles[] = $command.$action.'.php';
        }

        if($action == 'upgrade') {
            $upgrade_sql = glob($command.'upgrade_*.sql');
            $upgrade_inc = glob($command.'upgrade_*.php');
            foreach ($upgrade_sql as $filename) {
                $querys[] = $command.$filename.'.sql';
            }
            foreach ($upgrade_inc as $filename) {
                $incfiles[] = $command.$filename.'.sql';
            }
        }

    	if($querys) {
	        $connect = \think\Db::connect([], true);
	        $connect->execute("select 1");
		    foreach ($querys as $key => $file) {
		    	$query = @file_get_contents($file);
		    	$connect->getPdo()->exec($query);
		    }
    	}

    	if($incfiles) {
    		foreach ($incfiles as $filename) {
    			include $command.$filename.'.sql';
    		}
    	}
    	return true;
    }

    public function clear() {
        return \think\Cache::rm('__modules__');
    }


    // 更新菜单节点
    private function _rules($rule, $module = '') {
        if(empty($rule) || empty($module)) return;
        $result = model('AuthRule')->create([
				'pid'    => (int) $rule['pid'],
				'name'   => (string) $rule['name'],
				'type'   => (string) $rule['type'],
				'title'  => (string) $rule['title'],
				'icon'   => (string) $rule['icon'],
				'remark' => (string) $rule['remark'],
				'ismenu' => (int) $rule['ismenu'],
				'weigh'  => (int) $rule['weigh'],
				'module' => (string) $module,
				'status' => $rule['status'] ?: 'normal',
        ]);
        $pid = $result->id;
        if($rule['_child'] && $pid !== false) {
            foreach ($rule['_child'] as $r) {
                $r['pid'] = $pid;
                $this->_rules($r, $module);
            }
        }
        return;
    }

    // 检测依赖
    private function _depend($dependencies = [], $action = 'install') {
        foreach ($dependencies as $key => $value) {
            // print_r($)
        }
        return true;
    }

}